package course.requirements;

import java.util.Collection;
import java.util.HashSet;

import people.Person;
import people.Person.Name;
import people.student.Student;
import permission.role.AdministratorRole;
import course.Course;
import course.requirements.Requirement.RequirementType;
import evaluation.CourseEvaluation;

public enum RequirementManager {
	INSTANCE;
	
	private static final int MIN_POINTS_TO_PASS = 51;
	private static final Person ADMIN = new Person(new Name("admin", "admin"));
	static {
		ADMIN.addRole(new AdministratorRole());
	}
	
	public Collection<Course> getCourseListFromRequirementList(Collection<Requirement<?>> reqs) {
		Collection<Course> reqsToReturn = new HashSet<Course>();
		if(reqs == null) {
			return reqsToReturn;
		}
		
		RequirementType reqType;
		for(Requirement<?> req : reqs) {
			reqType = req.getRequirementType();
			Object reqObject = req.getRequirement();
			
			if(RequirementType.SINGLE.equals(reqType)) {
				reqsToReturn.add((Course)reqObject);
			} else if(RequirementType.MULTIPLE.equals(reqType)) {
				@SuppressWarnings("unchecked")
				Collection<Course> reqColl = (Collection<Course>)reqObject;
				for(Course c : reqColl) {
					reqsToReturn.add(c);
				}
			}
		}
		
		return reqsToReturn;
	}
	
	public boolean isStudentFulfillingRequirements(Student student, Course course) {
		if(student == null || course == null) {
			return false;
		}
		
		Collection<Course> courseReqs = course.getRequirements();
		if(courseReqs.isEmpty()) {
			return true;
		}
		
		Collection<CourseEvaluation> studentEvals = getEvalsForCourse(courseReqs, student.getCourseEvaluation(ADMIN));
		if(studentEvals.isEmpty()) {
			return false;
		}
		for(CourseEvaluation eval : studentEvals) {
			if(eval.getPoints() < MIN_POINTS_TO_PASS) {
				return false;
			}
		}
		return true;
	}
	
	private Collection<CourseEvaluation> getEvalsForCourse(Collection<Course> courseList, Collection<CourseEvaluation> evalList) {
		Collection<CourseEvaluation> evalsToReturn = new HashSet<CourseEvaluation>();
		for(CourseEvaluation eval : evalList) {
			if(!courseList.contains(eval.getCourse())) {
				continue;
			}
			evalsToReturn.add(eval);
		}
		return evalsToReturn;
	}
}
